<?php
namespace app\common\logic;
use app\common\model\Goods;
use app\common\model\Inviter;
use app\common\model\Member;
use app\common\model\Predeposit;
use think\Exception;
use think\Model;
use think\Db;

class Order extends Model
{

    /**
     * 佣金结算
     * @param $item
     * @return \multitype
     * @throws \think\exception\PDOException
     */
    public function settleOrderCommission($item) {
        $predeposit_model = new Predeposit();
        try {
            $order_model = new \app\common\model\Order();


            $act_config = [
                COMMISSION_SHARE    => 'order_commission_sale',
                COMMISSION_RETURN    => 'order_commission_return',
                COMMISSION_INVITER    => 'order_commission_inviter',
            ];
            $act = $act_config[$item['commission_type']];
            $predeposit_model->startTrans();

            $member = (new Member())->getMemberInfoByID($item['inviter_id']);
            // 余额变更
            $data = array();
            $data['member_id'] = $item['inviter_id'];
            $data['member_name'] = $member['member_name'];
            $data['amount'] = $item['amount'];
            $data['order_sn'] = $item['order_sn'];
            $data['admin_name'] = '系统';
            $data['lg_desc'] = $item['remark'];
            $predeposit_model->changePd($act, $data);

            $order_model->editOrder([
                'commission_state' => COMMISSION_STATE_SUCCESS,
                'commission_settle_time' => time(),
            ], ['order_id'=>$item['order_id']]);

            $result = Db::name('commission')->where(['id' => $item['id']])->update(['state' => COMMISSION_STATE_SUCCESS, 'update_time' => time()]);

            // 避免重复执行，未更新任何数据，说明可能已经结算
            if(!$result) throw new Exception('执行失败');
            $predeposit_model->commit();

            return sc_callback(true, '操作成功');

        } catch (\Exception $e) {
            $predeposit_model->rollback();
            throw $e;
        }
    }

    /**
     * 计算订单佣金
     * @param $order_info
     * @return void
     * @throws Exception
     * @throws \think\exception\PDOException
     */
    public function calcOrderCommission($order_info) {
        if(!$order_info['inviter_id']) return;
        $member_model = new Member();
        $order_model = new \app\common\model\Order();
        $goods_model = new Goods();
        $inviter_model = new Inviter();

        $order_goods = $order_model->getOrdergoodsList(['order_id' => $order_info['order_id']]);
        // 代理商信息
        $inviter_info = $inviter_model->getInviterInfo(['i.inviter_id' => $order_info['inviter_id']]);
        $level = $inviter_info['inviter_type'];
        $list = [];
        // 计算订单分享佣金
        $commission_sale = 0;
        $commission = 0;
        $stat = [];
        foreach ($order_goods as $item) {
            $snapshot = json_decode($item['snapshot'], true);
            $goods_info = $snapshot['goods_info'];

            // 销售佣金(全部商品)
            $goods_commission = $item['goods_pay_price'] - $goods_info['goods_price_' . $level] * $item['goods_num'];
            $commission += $goods_commission;
            isset($stat[$item['rec_id']]) or $stat[$item['rec_id']] = [
                'commission' => 0,
                'commission_sale' => 0,
            ];
            $stat[$item['rec_id']]['commission_sale'] += $goods_commission;
            $stat[$item['rec_id']]['commission'] += $goods_commission;
        }

        // 保留4位有效数组
        $commission = round($commission, 4);

        $commission_sale = $commission;

        $commission_type = $order_info['order_buy_type'] == ORDER_BUY_SELF ? COMMISSION_RETURN : COMMISSION_SHARE;
        $list[] = [
            'commission_type' => $commission_type,
            'order_id'  => $order_info['order_id'],
            'member_id' => $order_info['buyer_id'],
            'member_name' => $order_info['buyer_name'],
            'inviter_id' => $inviter_info['inviter_id'],
            'inviter_name' => $inviter_info['inviter_name'],
            'order_sn'  => $order_info['order_sn'],
            'amount'    => $commission,
            'state'     => COMMISSION_STATE_NEW,
            'remark'    => dict_convert('commission_type', $commission_type),
            'update_time'   => time(),
            'create_time'   => time(),
        ];

        $level = $inviter_info['inviter_type'];
        $has_parent = true;

        while($has_parent) {
            // 用户信息
            $member_info = $member_model->getMemberInfoByID($inviter_info['inviter_id']);
            if(!$member_info) {
                $has_parent = false;
                continue;
            }
            // 上级代理商
            $inviter_info = $inviter_model->getInviterInfo([
                'i.inviter_id' => $member_info['inviter_id'],
                'i.inviter_type' => ['lt', $level],     // 上级
            ]);
            if(!$inviter_info) {
                $has_parent = false;
                continue;
            }

            $child_level = $level;
            $level = $inviter_info['inviter_type'];
            $has_parent = $level != 1;

            $commission = 0;
            foreach ($order_goods as $item) {
                $snapshot = json_decode($item['snapshot'], true);
                $goods_info = $snapshot['goods_info'];
                $goods_commission = ($goods_info['goods_price_'.($child_level)] - $goods_info['goods_price_'.$level]) * $item['goods_num'];
                $commission += $goods_commission;
                $stat[$item['rec_id']]['commission'] += $goods_commission;
            }

            // 保留4位有效数组
            $commission = round($commission, 4);

            $list[] = [
                'commission_type' => COMMISSION_INVITER,    // 代理佣金
                'order_id'  => $order_info['order_id'],
                'member_id' => $member_info['member_id'],
                'member_name' => $member_info['member_name'],
                'inviter_id' => $inviter_info['inviter_id'],
                'inviter_name' => $inviter_info['inviter_name'],
                'order_sn'  => $order_info['order_sn'],
                'amount'    => $commission,
                'state'     => COMMISSION_STATE_NEW,
                'remark'    => dict_convert('commission_type', COMMISSION_INVITER),
                'update_time'   => time(),
                'create_time'   => time(),
            ];
        }

        // 记录佣金
        foreach ($order_goods as $item) {
            if($stat[$item['rec_id']]) {
                $order_model->editOrdergoods($stat[$item['rec_id']], [
                    'order_id' => $item['order_id'],
                    'rec_id' => $item['rec_id']
                ]);
            }
        }

        // 记录佣金
        if($list) Db::name('commission')->insertAll($list);

        // 标记订单状态
        $total_commission = array_sum(array_column($list, 'amount'));
        $order_model->editOrder([
            'commission'    => $total_commission,    // 记录该笔订单总佣金
            'commission_sale'    => $commission_sale,    // 记录返现或销售佣金
            'commission_state' => COMMISSION_STATE_NEW,  // 分佣状态,若无分佣，则直接标记为分佣完成
        ], ['order_id' => $order_info['order_id']]);
    }

    /**
     * 取消订单
     * @param array $order_info
     * @param string $role 操作角色 buyer、admin、system 分别代表买家、管理员、系统
     * @param string $user 操作人
     * @param string $msg 操作备注
     * @param boolean $if_update_account 是否变更账户金额
     * @param boolean $if_queue 是否使用队列
     * @param boolean $if_pay 是否已经支付,已经支付则全部退回支付金额
     * @return array
     */
    public function changeOrderStateCancel($order_info, $role, $user = '', $msg = '', $if_update_account = true, $if_quque = true,$if_pay=false)
    {
        try {
            $order_model = model('order');
            $order_model->startTrans();
            $order_id = $order_info['order_id'];

            //库存销量变更
            $goods_list = $order_model->getOrdergoodsList(array('order_id' => $order_id));
            $data = array();
            foreach ($goods_list as $goods) {
                $data[$goods['goods_id']] = $goods['goods_num'];
            }
            if ($if_quque) {
                \mall\queue\QueueClient::push('cancelOrderUpdateStorage', $data);
            }
            else {
                \model('queue','logic')->cancelOrderUpdateStorage($data);
            }

            if ($if_update_account) {
                $predeposit_model = model('predeposit');
                //解冻充值卡
                $rcb_amount = floatval($order_info['rcb_amount']);
                if ($rcb_amount > 0) {
                    $data_pd = array();
                    $data_pd['member_id'] = $order_info['buyer_id'];
                    $data_pd['member_name'] = $order_info['buyer_name'];
                    $data_pd['amount'] = $rcb_amount;
                    $data_pd['order_sn'] = $order_info['order_sn'];
                    $predeposit_model->changeRcb('order_cancel', $data_pd);
                }

                //注意：当用户全额使用预存款进行支付,并不会冻结, 当用户使用部分预存款进行支付,支付的预存款则会冻结.也就是支付成功之后不会有冻结资金,当未支付成功,使用的预付款变为冻结资金。

                if($order_info['order_state'] == ORDER_STATE_NEW){
                    //当是已下单,未支付(可能包含部分款项使用预存款,预存款在冻结资金),则退还预存款,取消订单
                    $pd_amount = floatval($order_info['pd_amount']);
                    if ($pd_amount > 0) {
                        $data_pd = array();
                        $data_pd['member_id'] = $order_info['buyer_id'];
                        $data_pd['member_name'] = $order_info['buyer_name'];
                        $data_pd['amount'] = $pd_amount;
                        $data_pd['order_sn'] = $order_info['order_sn'];
                        $predeposit_model->changePd('order_cancel', $data_pd);
                    }
                }

                if($order_info['order_state'] == ORDER_STATE_PAY){
                    //当是已付款,未发货状态,则直接取消订单, 订单金额减去充值卡  表示为支付的总金额(预存款部分支付,以及直接支付),已付款预存款部分支付的金额已被取消冻结了.
                    $payment_amount = $order_info['order_amount'] - $rcb_amount;
                    if ($payment_amount > 0) {
                        $data_pd = array();
                        $data_pd['member_id'] = $order_info['buyer_id'];
                        $data_pd['member_name'] = $order_info['buyer_name'];
                        $data_pd['amount'] = $payment_amount;
                        $data_pd['order_sn'] = $order_info['order_sn'];
                        $predeposit_model->changePd('refund', $data_pd);
                    }
                }

            }

            //更新订单信息
            $update_order = array('order_state' => ORDER_STATE_CANCEL, 'pd_amount' => 0);
            $update = $order_model->editOrder($update_order, array('order_id' => $order_id));
            if (!$update) {
                exception('保存失败');
            }

            //添加订单日志
            $data = array();
            $data['order_id'] = $order_id;
            $data['log_role'] = $role;
            $data['log_msg'] = '取消了订单';
            $data['log_user'] = $user;
            if ($msg) {
                $data['log_msg'] .= ' ( ' . $msg . ' )';
            }
            $data['log_orderstate'] = ORDER_STATE_CANCEL;
            $order_model->addOrderlog($data);

            // 退货或者超时，修改库存记录
            // 查询当前订单中的商品信息
            $order_goods = db("ordergoods")->alias("og")->join("goods g","g.goods_id=og.goods_id","LEFT")->where(["og.order_id"=>$order_info['order_id']])->field("og.goods_num,g.goods_id,g.goods_storage,g.goods_name")->select();
            // 根据商品信息添加库存记录
            $data_storage = [];
            foreach ($order_goods as $k => $v){
                if($v["goods_id"]){
                    $data_storage[] = [
                        "log_type" => 5,
                        "goods_name" => $v["goods_name"],
                        "goods_id" => $v["goods_id"],
                        "erp_storage" => $v["goods_num"],
                        "goods_storage" => $v["goods_storage"],
                        "order_sn" => $order_info['order_sn'],
                        "content" => "用户【".$order_info['buyer_name']."】取消订单，增加库存",
                    ];
                }
            }
            if($data_storage){
                $res_goods_storage = model("goodsStorageLog")->addStorageAll($data_storage);
                if(!$res_goods_storage){
                    exception('库存记录保存失败');
                }
            }
            $order_model->commit();

            return sc_callback(true, '操作成功');

        } catch (\Exception $e) {
            $this->rollback();
            return sc_callback(false, '操作失败');
        }
    }

    /**
     * 收货
     * @param array $order_info
     * @param string $role 操作角色 buyer、admin、system 分别代表买家、管理员、系统
     * @param string $user 操作人
     * @param string $msg 操作备注
     * @return array
     */
    public function changeOrderStateReceive($order_info, $role, $user = '', $msg = '')
    {
        try {
            $member_id = $order_info['buyer_id'];
            $order_id = $order_info['order_id'];
            $order_model = model('order');

            $order_model->startTrans();

            //更新订单状态
            $update_order = array();
            $update_order['finnshed_time'] = TIMESTAMP;
            $update_order['order_state'] = ORDER_STATE_SUCCESS;
            $update = $order_model->editOrder($update_order, array('order_id' => $order_id));
            if (!$update) {
                exception('保存失败');
            }

            //添加订单日志
            $data = array();
            $data['order_id'] = $order_id;
            $data['log_role'] = 'buyer';
            $data['log_msg'] = '签收了货物';
            $data['log_user'] = $user;
            if ($msg) {
                $data['log_msg'] .= ' ( ' . $msg . ' )';
            }

            $data['log_orderstate'] = ORDER_STATE_SUCCESS;
            $order_model->addOrderlog($data);

            //分发分享积分
            $orderinviter_model = model('orderinviter');
            $orderinviter_model->givePoints($order_id, false);

            //添加会员积分
            if (config('points_isuse') == 1) {
                model('points')->savePointslog('order', array(
                    'pl_memberid' => $order_info['buyer_id'], 'pl_membername' => $order_info['buyer_name'],
                    'orderprice' => $order_info['order_amount'], 'order_sn' => $order_info['order_sn'],
                    'order_id' => $order_info['order_id']
                ), true);
            }

            //添加会员经验值
            model('exppoints')->saveExppointslog('order', array(
                'explog_memberid' => $order_info['buyer_id'], 'explog_membername' => $order_info['buyer_name'],
                'orderprice' => $order_info['order_amount'], 'order_sn' => $order_info['order_sn'],
                'order_id' => $order_info['order_id']
            ), true);
            //邀请人获得返利积分
            $inviter_id = sc_getvalue_byname('member', 'member_id', $member_id, 'inviter_id');
            if(!empty($inviter_id)) {
                $inviter_name = sc_getvalue_byname('member', 'member_id', $inviter_id['inviter_id'], 'member_name');
                $rebate_amount = ceil(0.01 * $order_info['order_amount'] * config('points_rebate'));
                model('points')->savePointslog('rebate', array(
                    'pl_memberid' => $inviter_id['inviter_id'], 'pl_membername' => $inviter_name, 'pl_points' => $rebate_amount
                ), true);
            }
            $order_model->commit();
            return sc_callback(true, '操作成功');
        } catch (\Exception $e) {
            $order_model->rollback();
            return sc_callback(false, '操作失败');
        }
    }

    /**
     * 更改运费
     * @param array $order_info
     * @param string $role 操作角色 buyer、admin、system 分别代表买家、管理员、系统
     * @param string $user 操作人
     * @param float $price 运费
     * @return array
     */
    public function changeOrderShipPrice($order_info, $role, $user = '', $price)
    {
        try {

            $order_id = $order_info['order_id'];
            $order_model = model('order');

            $data = array();
            $data['shipping_fee'] = abs(floatval($price));
            $data['order_amount'] = Db::raw('goods_amount+'.$data['shipping_fee']);
            $update = $order_model->editOrder($data, array('order_id' => $order_id));
            if (!$update) {
                exception('保存失败');
            }
            //记录订单日志
            $data = array();
            $data['order_id'] = $order_id;
            $data['log_role'] = $role;
            $data['log_user'] = $user;
            $data['log_msg'] = '修改了运费' . '( ' . $price . ' )';;
            $data['log_orderstate'] = $order_info['payment_code'] == 'offline' ? ORDER_STATE_PAY : ORDER_STATE_NEW;
            $order_model->addOrderlog($data);
            return sc_callback(true, '操作成功');
        } catch (\Exception $e) {
            return sc_callback(false, '操作失败');
        }
    }

    /**
     * 更改运费
     * @param array $order_info
     * @param string $role 操作角色 buyer、admin、system 分别代表买家、管理员、系统
     * @param string $user 操作人
     * @param float $price 运费
     * @return array
     */
    public function changeOrderSpayPrice($order_info, $role, $user = '', $price)
    {
        try {

            $order_id = $order_info['order_id'];
            $order_model = model('order');

            $data = array();
            $data['goods_amount'] = abs(floatval($price));
            $data['order_amount'] = Db::raw('shipping_fee+'.$data['goods_amount']);
            $update = $order_model->editOrder($data, array('order_id' => $order_id));
            if (!$update) {
                exception('保存失败');
            }
            //记录订单日志
            $data = array();
            $data['order_id'] = $order_id;
            $data['log_role'] = $role;
            $data['log_user'] = $user;
            $data['log_msg'] = '修改了运费' . '( ' . $price . ' )';;
            $data['log_orderstate'] = $order_info['payment_code'] == 'offline' ? ORDER_STATE_PAY : ORDER_STATE_NEW;
            $order_model->addOrderlog($data);
            return sc_callback(true, '操作成功');
        } catch (\Exception $e) {
            return sc_callback(false, '操作失败');
        }
    }

    /**
     * 回收站操作（放入回收站、还原、永久删除）
     * @param array $order_info
     * @param string $role 操作角色 buyer、admin、system 分别代表买家、管理员、系统
     * @param string $state_type 操作类型
     * @return array
     */
    public function changeOrderStateRecycle($order_info, $role, $state_type)
    {
        $order_id = $order_info['order_id'];
        $order_model = model('order');
        //更新订单删除状态
        $state = str_replace(array('delete', 'drop', 'restore'), array(
            ORDER_DEL_STATE_DELETE, ORDER_DEL_STATE_DROP, ORDER_DEL_STATE_DEFAULT
        ), $state_type);
        $update = $order_model->editOrder(array('delete_state' => $state), array('order_id' => $order_id));
        if (!$update) {
            return sc_callback(false, '操作失败');
        }
        else {
            return sc_callback(true, '操作成功');
        }
    }

    /**
     * 发货
     * @param array $order_info
     * @param string $role 操作角色 buyer、admin、system 分别代表买家、管理员、系统
     * @param string $user 操作人
     * @return array
     */
    public function changeOrderSend($order_info, $role, $user = '', $post = array())
    {
        $order_id = $order_info['order_id'];
        $order_model = model('order');

        //查看是否为拼团订单
        $condition = array();
        $condition['order_id'] = $order_id;
        $pintuanorder = model('ppintuanorder')->getOnePpintuanorder($condition);
        if (!empty($pintuanorder) && $pintuanorder['pintuanorder_state'] != 2) {
            return sc_callback(FALSE, '拼团订单暂时不允许发货');
        }

        try {
            $order_model->startTrans();
            $data = array();
            $data['reciver_name'] = $post['reciver_name'];
            $data['reciver_info'] = $post['reciver_info'];
            $data['deliver_explain'] = $post['deliver_explain'];
            $data['daddress_id'] = intval($post['daddress_id']);
            $data['shipping_express_id'] = intval($post['express_id']);
            $data['shipping_time'] = TIMESTAMP;

            $condition = array();
            $condition['order_id'] = $order_id;
            $update = $order_model->editOrdercommon($data, $condition);
            if (!$update) {
                exception('操作失败');
            }

            $data = array();
            $data['shipping_code'] = isset($post['shipping_code'])?$post['shipping_code']:'';
            $data['order_state'] = ORDER_STATE_SEND;
            $data['delay_time'] = TIMESTAMP;
            $update = $order_model->editOrder($data, $condition);
            if (!$update) {
                exception('操作失败');
            }

            // 发货后增加商品库存记录
            $order_goods = db("ordergoods")->alias("og")->join("goods g","g.goods_id=og.goods_id")->where(["og.order_id"=>$order_id])->field("og.goods_num,g.goods_id,g.goods_name,g.goods_storage")->select();
            foreach ($order_goods as $k => $v) {
                $data_storage[] = [
                    "log_type" => 4,
                    "goods_name" => $v["goods_name"],
                    "goods_id" => $v["goods_id"],
                    "erp_storage" => 0,
                    "goods_storage" => $v["goods_storage"],
                    "order_sn" => $order_info["order_sn"],
                    "content" => "发货,扣除锁定库存",
                ];
            }
            $res_storage = model("goodsStorageLog")->addStorageAll($data_storage);
            if(!$res_storage){
                exception('库存记录写入失败');
            }

            $order_model->commit();
        } catch (\Exception $e) {
            $order_model->rollback();
            return sc_callback(false, $e->getMessage());
        }


        //添加订单日志
        $data = array();
        $data['order_id'] = intval($order_id);
        $data['log_role'] = 'admin';
        $data['log_user'] = session('member_name');
        $data['log_msg'] = '发出了货物 ( 编辑了发货信息 )';
        $data['log_orderstate'] = ORDER_STATE_SEND;
        $order_model->addOrderlog($data);

        // 发送买家消息
        $param = array();
        $param['code'] = 'order_deliver_success';
        $param['member_id'] = $order_info['buyer_id'];
        $param['param'] = array(
            'order_sn' => $order_info['order_sn'],
            'order_url' => url('home/Memberorder/show_order', array('order_id' => $order_id))
        );
         \mall\queue\QueueClient::push('sendMemberMsg', $param);
        return sc_callback(true, '操作成功');
    }

    /**
     * 收到货款
     * @param array $order_info
     * @param string $role 操作角色 buyer、admin、system 分别代表买家、管理员、系统
     * @param string $user 操作人
     * @return array
     */
    public function changeOrderReceivePay($order_list, $role, $user = '', $post = array())
    {
        $order_model = model('order');

        try {
            $order_model->startTrans();

            $data = array();
            $data['api_paystate'] = 1;

            $update = $order_model->editOrderpay($data, array('pay_sn' => $order_list[0]['pay_sn']));
            if (!$update) {
                 \Exception('更新支付单状态失败');
            }

            $predeposit_model = model('predeposit');
            foreach ($order_list as $order_info) {
                $order_id = $order_info['order_id'];
                if ($order_info['order_state'] != ORDER_STATE_NEW)
                    continue;
                //下单，支付被冻结的充值卡
                $rcb_amount = floatval($order_info['rcb_amount']);
                if ($rcb_amount > 0) {
                    $data_pd = array();
                    $data_pd['member_id'] = $order_info['buyer_id'];
                    $data_pd['member_name'] = $order_info['buyer_name'];
                    $data_pd['amount'] = $rcb_amount;
                    $data_pd['order_sn'] = $order_info['order_sn'];
                    $predeposit_model->changeRcb('order_comb_pay', $data_pd);
                }

                //下单，支付被冻结的预存款
                $pd_amount = floatval($order_info['pd_amount']);
                if ($pd_amount > 0) {
                    $data_pd = array();
                    $data_pd['member_id'] = $order_info['buyer_id'];
                    $data_pd['member_name'] = $order_info['buyer_name'];
                    $data_pd['amount'] = $pd_amount;
                    $data_pd['order_sn'] = $order_info['order_sn'];
                    $predeposit_model->changePd('order_comb_pay', $data_pd);
                }
            }

            //更新订单状态
            $update_order = array();
            $update_order['order_state'] = ORDER_STATE_PAY;
            $update_order['payment_time'] = (isset($post['payment_time']) ? strtotime($post['payment_time']) : TIMESTAMP);
            $update_order['payment_code'] = $post['payment_code'];
            $update_order['trade_no'] = $post['trade_no'];
            $update = $order_model->editOrder($update_order, array(
                'pay_sn' => $order_info['pay_sn'],
                'order_state' => ORDER_STATE_NEW,
            ));
            if (!$update) {
                exception('操作失败');
            }
            $order_model->commit();
        } catch (\Exception $e) {
            $order_model->rollback();
            return sc_callback(false, $e->getMessage());
        }

        foreach ($order_list as $order_info) {
            //防止重复发送消息
            if ($order_info['order_state'] != ORDER_STATE_NEW)
                continue;
            $order_id = $order_info['order_id'];
            // 支付成功发送买家消息
            $param = array();
            $param['code'] = 'order_payment_success';
            $param['member_id'] = $order_info['buyer_id'];
            $param['param'] = array(
                'order_sn' => $order_info['order_sn'],
                'order_url' => url('home/Memberorder/show_order', array('order_id' => $order_info['order_id']))
            );
             \mall\queue\QueueClient::push('sendMemberMsg', $param);


            //添加订单日志
            $data = array();
            $data['order_id'] = $order_id;
            $data['log_role'] = $role;
            $data['log_user'] = $user;
            $data['log_msg'] = '收到了货款 ( 支付平台交易号 : ' . $post['trade_no'] . ' )';
            $data['log_orderstate'] = ORDER_STATE_PAY;
            $order_model->addOrderlog($data);
        }

        return sc_callback(true, '操作成功');
    }
}
